<?php

namespace app\common\library\device\cabinet;

use addons\mycurrency\library\Common;
use app\common\model\Config;
use app\common\model\Error;
use app\common\model\mycurrency\Device;
use app\common\model\mycurrency\DeviceInstruction;
use app\common\model\mycurrency\DeviceLattice;
use app\common\model\mycurrency\LeaseOrder;
use app\common\model\mycurrency\LeaseOrderDevice;
use BugHonorFileTimeTest\BugHonorFileTimeTest;
use think\Db;
use think\Hook;
use think\Log;
use think\Queue;
use function think\__require_file;

/**
 * 逻辑处理
 */
class Logic
{
    /**
     * 设备消息日志处理
     */
    public static function index($topic,$data){
        $code = $data['code'];
        $message = $data['message'];
        $instruction_extend = [];//日志扩展数据
        if ($code != Analysis::CODE_SHANGXIAN){
            //查询设备
            $device = Device::where([
                'serial_number' => $data['from'],
                'deletetime' => null,
            ])->find();
            if(!$device){
                return;
            }
            if ($device->is_online == Device::IS_ONLINE_BUZAIXIAN){
                $device->is_online = Device::IS_ONLINE_ZAIXIAN;
                $device->save();
            }
            $device_id = $device->id;
        }
        //根据指令类型做逻辑处理
        switch ($code) {
            case Analysis::CODE_KAIMENSONGDA://设备应答服务器指令【开门结果应答】 21
                $instruction_extend = self::dorrOpeningControlService($device_id,$data);
                break;
            case Analysis::CODE_KAIMENZHIXING://设备应答服务器开门执行结果 23
                $instruction_extend = self::dorrOpeningResult($device_id,$data);
                break;
            case Analysis::CODE_GEKOUZHUAGNTAI://设备上报归还执行结果【柜门状态发生变化都会上报】 20
                $instruction_extend = self::cabinetdoorStateChange($device_id,$data);
                break;
            case Analysis::CODE_CHAXUNZHUANGTAI://设备应答服务器查询结果【服务器查询柜门状态指令应答】 24
                $instruction_extend = self::cabinetDoorState($device_id,$data);
                break;
            case Analysis::CODE_ZHUANGTAIYINGDA://设备应答服务器查询结果【服务器查询柜门状态指令应答】 25
                $instruction_extend = self::cabinetDoorState($device_id,$data);
                break;
            case Analysis::CODE_YINGDACHUANGGANQI://设备应答开关传感器状态查询【服务器查询传感器状态】 51
                $instruction_extend = self::sensorState($device_id,$data);
                break;
            case Analysis::CODE_YINGDAWANGLUO://设备应答服务器查询结果【服务器查询网络指令应答】 101
                $p_instruction = DeviceInstruction::where([
                    'device_id' => $device_id,
                    'code' => Analysis::CODE_CHAXUNWANGLUO,
                    'message_id' => $data['message_id'],
                    'deletetime' => null
                ])->order('id desc')->find();
                $p_message = explode(',',json_decode($p_instruction['message'],true)['m']);
                $params = [
                    'ip' => $p_message[0],
                    'port' => $p_message[1],
                    'number' => $p_message[2],
                    'password' => $p_message[3],
                    'theme' => explode('/',$topic)[1],
                ];
                Device::network(Analysis::CODE_NETWORK_1,$device_id,$params);
                break;
            case Analysis::CODE_SHANGXIAN://设备上线
                $device_id = self::goOnline($data['from'],$message);
                break;
            case Analysis::CODE_LIXIAN://设备离线
                self::offline($device_id,$message);
                break;
            case Analysis::CODE_XINTIAO://设备心跳包
                self::heartbeat($device_id,$message);
                break;
            case Analysis::CODE_BUKA://服务器读卡指令应答  110
                $instruction_extend = self::cardID($device_id,$data);
                break;
            case Analysis::CODE_DUKAYINGDA://服务器读卡指令应答 111
                $instruction_extend = self::cardID($device_id,$data);
                break;
            default:
                break;
        }
        //保存日志
        $instruction_id = DeviceInstruction::increase($device_id,$code,json_encode($data),$data['message_id'],$instruction_extend);
        //更新message_id 应答指令不需要更新 指令id
        if (
            $code != Analysis::CODE_KAIMENSONGDA &&
            $code != Analysis::CODE_KAIMENZHIXING &&
            $code != Analysis::CODE_GEKOUZHUAGNTAI &&
            $code != Analysis::CODE_ZHUANGTAIYINGDA &&
            $code != Analysis::CODE_YINGDACHUANGGANQI &&
            $code != Analysis::CODE_YINGDAWANGLUO &&
            $code != Analysis::CODE_KAIDENGYINGDA &&
            $code != Analysis::CODE_DUKAYINGDA
        )
        {
            Analysis::messageidUpdate($device_id,$data['message_id']);
        }
    }

    /**
     * 设备上线
     * @param string $serial_number 设备唯一序列号
     * @param array $message 设备上报内容
     */
    public static function goOnline($serial_number,$message){
        $device = Device::where(['serial_number' => $serial_number,'deletetime' => null])->find();
        if (!$device){//设备不存在，首先添加设备
            $number = Device::getNumger();
            $content = config("site.Host") . "device/{$number}";//称重台二维码内容
            //$qrcode_image = Common::getCodewmImage($content,'device');
            $increase = [
                'number' => $number,
                'serial_number' => $serial_number,
                'status' => Device::STATUS_ZHENGCHENG,
                'is_fault' => Device::IS_FAULT_WU,
                'createtime' => time(),
                'qrcode_image' => '',//$qrcode_image,
            ];
            $device = Device::create($increase);

            //批量生成格口
            $n = 6;
            $device_lattice = [];
            for ($i=1; $i<=$n; $i++)
            {
                $device_lattice[] = [
                    'device_id' => $device->id,
                    'number' => $i,
                    'status' => DeviceLattice::STATUS_ZHENGCHENG,
                    'use_status' => DeviceLattice::USE_STATUS_WUGAN,
                    'is_fault' => DeviceLattice::IS_FAULT_WU,
                    'createtime' => time(),
                ];
            }
            $deviceLattice_model = new DeviceLattice();
            $deviceLattice_model->saveAll($device_lattice);
        }
        $device->is_online = Device::IS_ONLINE_ZAIXIAN;
        $device->rssi = $message['rssi'];
        $device->network = $message['net'];
        $device->dev = $message['dev'];
        $device->iccid = $message['iccid'];
        $device->save();
        //设置心跳上报间隔
        Control::sending($device['id'],Analysis::CODE_XINTIAO_PEIZHI,'120',[]);
        return $device->id;
    }

    /**
     * 设备离线
     * @param int $device_id 设备id
     * @param array $message 设备上报内容
     */
    public static function offline($device_id,$message){
        $device = Device::where(['id' => $device_id,'deletetime' => null])->find();
        if(!$device){
            return;
        }
        $device->is_online = Device::IS_ONLINE_BUZAIXIAN;
        $device->rssi = $message['rssi'];
        $device->network = $message['net'];
        $device->dev = $message['dev'];
        $device->save();
    }

    /**
     * 设备心跳包
     * @param int $device_id 设备id
     * @param array $message 设备上报内容
     */
    public static function heartbeat($device_id,$message){
        $device = Device::where(['id' => $device_id,'deletetime' => null])->find();
        if(!$device){
            return;
        }
        $device->rssi = $message['rssi'];
        $device->network = $message['net'];
        $device->dev = $message['dev'];
        $device->heartbeat_time = time();
        $device->save();
    }

    /**
     * 开门指令发送到设备通知
     * @param int $device_id 设备id
     * @param array $message 设备上报内容
     */
    public static function dorrOpeningControlService($device_id,$message){
        $instruction = DeviceInstruction::where(['device_id' => $device_id,'code' => Analysis::CODE_KAIMEN,'message_id' => $message['message_id'],'deletetime' => null])->order('id desc')->find();
        if ($instruction){
            $instruction->control_status = DeviceInstruction::CONTROL_STATUS_YISONGDA;
            $instruction->save();
        }
        return [
            'device_lattice_id' => $instruction->device_lattice_id,
            'lease_order_device_id' => $instruction->lease_order_device_id,
        ];
    }

    /**
     * 开门结果应答
     * @param int $device_id 设备id
     * @param array $message 设备上报内容
     */
    public static function dorrOpeningResult($device_id,$message){
        trace('========================接收到消息-设备开门执行结果-进入执行逻辑方法==============================');
        $instruction = DeviceInstruction::where([
            'device_id' => $device_id,
            'code' => Analysis::CODE_KAIMEN,
            'message_id' => $message['message_id'],
            'deletetime' => null
        ])->order('id desc')
            ->find();
        if ($instruction){
            if ($instruction->code == Analysis::CODE_KAIMEN){//应答的是控制开门指令
                //修改指令状态
                $instruction->control_status = DeviceInstruction::CONTROL_STATUS_YIYINGDA;//指令已应答
                $instruction->save();

                //根据控制类型做相应处理
                switch ($instruction->control_type) {
                    case DeviceInstruction::CONTROL_TYPE_ZUJIEKAIMEN://用户租赁开门
                        trace('========================开始处理租赁逻辑1==============================' . $device_id . '================' .json_encode($message));
                        LeaseOrderDevice::deviceOpenResult($instruction->lease_order_device_id,$message['message']['result']);
                        break;
                    case DeviceInstruction::CONTROL_TYPE_GUIHUANKAIMEN://用户归还开门
                        $lease_order_device = LeaseOrderDevice::get($instruction->lease_order_device_id);
                        if($lease_order_device){
                            if($message['message']['result'] != 0){//开门失败 - 订单设备使用记录更新到使用中状态
                                $lease_order_device->status = LeaseOrderDevice::STATUS_SHIYONGZHONG;//使用状态 改为使用中
                                $lease_order_device->return_open_progress = LeaseOrderDevice::RETURN_OPEN_PROGRESS_KAIMENSHIBAI;//归还开门进度修改为开门失败
                                $lease_order_device->save();
                            }else{//开门成功
                                $open_type = explode(',',json_decode($instruction->message,true)['m'])[0];//操作开门流程
                                $lease_order_device->return_open_progress = LeaseOrderDevice::RETURN_OPEN_PROGRESS_YIKAIMEN;//归还开门进度修改为已开门
                                $lease_order_device->save();
                                if($open_type == 49){
                                    //如果是普通开门 不会上报 c20 那么需要主动去查询
                                    $queue_default = config('queue.default');
                                    Queue::later(5, "addons\mycurrency\controller\job\Lease@returnInspect", ['lease_order_device_id' => $lease_order_device['id']], $queue_default);
                                }
                            }
                        }
                        break;
                    default:
                        break;
                }
            }
            return [
                'device_lattice_id' => $instruction->device_lattice_id,
                'lease_order_device_id' => $instruction->lease_order_device_id,
            ];
        }
        //开门成功主动开灯
//        if($message['message']['result'] == 0){//开门成功，控制开灯
//            $data = "{$message['message']['number']}&2&30";
//            Control::sending($device_id,Analysis::CODE_KAIDENG,$data,[]);
//        }
        return [];
    }

    /**
     * 柜门状态变化通知
     * @param int $device_id 设备id
     * @param array $message 设备上报内容
     */
    public static function cabinetdoorStateChange($device_id,$message){
        trace('========================开始处理结束订单1==============================' . $device_id . '================' . json_encode($message));
        $device_lattice = DeviceLattice::where(['device_id' => $device_id,'number' => $message['message']['number'],'deletetime' => null])->find();//查询设备隔扣信息
        trace('========================开始处理结束订单2 查询出柜门信息==============================' . json_encode($device_lattice));
        if (!$device_lattice){
            return;
        }
        trace('========================开始处理结束订单3==============================');
        $result = $message['message']['result'];
        //if ($result == 0){//成功，关门设备已归还
        Db::startTrans();
        try {
            trace('========================开始处理结束订单4==============================格扣id:' . $device_lattice->id . '===============执行结果：' . $result);
            $order_device_id = LeaseOrderDevice::deviceReturn($device_lattice->id,$result);
            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            trace('========================开始处理结束订单101==============================' . $e->getMessage());
        }
        return [
            'device_lattice_id' => $device_lattice->id,
            'lease_order_device_id' => $order_device_id,
        ];
        //}
    }

    /**
     * 服务器查询柜门状态应答
     */
    public static function cabinetDoorState($device_id,$message){
        $instruction = DeviceInstruction::where([
            'device_id' => $device_id,
            'code' => Analysis::CODE_CHAXUNZHUANGTAI,
            'message_id' => $message['message_id'],
            'deletetime' => null
        ])->order('id desc')->find();


        $return = [];
        if($instruction){
            //修改查询指令状态
            $instruction->control_status = DeviceInstruction::CONTROL_STATUS_YIYINGDA;
            $instruction->save();
            //租赁订单归还关门超时发送指令查询柜门状态
            if ($instruction->control_type == DeviceInstruction::CONTROL_TYPE_GUIHUANGUANMENCHAOSHI){
                //修改个口是否有杆
                $lattice = DeviceLattice::get($instruction->device_lattice_id);
                if($message['message']['state_str'] == 0){
                    $lattice->use_status = DeviceLattice::USE_STATUS_YOUGAN;
                }else{
                    $lattice->use_status = DeviceLattice::USE_STATUS_WUGAN;
                }
                $lattice->save();
                //判断是否需要处理订单
                if($instruction->control_type == DeviceInstruction::CONTROL_TYPE_GUIHUANGUANMENCHAOSHI){//租赁订单关门超时发送的查询柜门状态指令
                    trace('========================开始处理结束订单201-1 租赁订单关门超时发送的查询柜门状态指令==============================' . $instruction->lease_order_device_id);
                    $lease_order_device = LeaseOrderDevice::get($instruction->lease_order_device_id);
                    Db::startTrans();
                    try {
                        $order_device_id = LeaseOrderDevice::deviceReturn($lease_order_device->device_lattice_id,$message['message']['state_str']);
                        $return['lease_order_device_id'] = $order_device_id;
                        Db::commit();
                    } catch (Exception $e) {
                        Db::rollback();
                        echo $e->getMessage();
                    }
                }
            }
            //管理员查询柜门开关状态
            else if ($instruction->control_type == DeviceInstruction::CONTROL_TYPE_GUIMENKAIGUANZHUANGTAI){
                //修改门状态
                $lattice = DeviceLattice::get($instruction->device_lattice_id);
                $lattice->door_time = time();
                if($message['message']['state_str'] == 1){//未关门
                    $lattice->door_state = 1;
                }else{//已关门
                    $lattice->door_state = 0;
                }
                $lattice->save();
            }
            //归还检测流程查询门是否关闭
            else if($instruction->control_type == DeviceInstruction::CONTROL_TYPE_GUIHUANJIANCEMENSHIFOUGUANBI){
                $order_device_id = LeaseOrderDevice::detectionResponse(LeaseOrderDevice::DETECTION_TYPE_door,$instruction->lease_order_device_id,$message);
                $return['lease_order_device_id'] = $order_device_id;
            }
        }
        return $return;
    }

    /**
     * 传感器状态查询应答
     */
    public static function sensorState($device_id,$message){
        $return = [];
        $instruction = DeviceInstruction::where(['device_id' => $device_id,'code' =>Analysis::CODE_CHAXUNCHUANGANQI, 'message_id' => $message['message_id'],'deletetime' => null])->order('id desc')->find();
        if(!$instruction){
            return [];
        }
        if ($instruction->control_type == DeviceInstruction::CONTROL_TYPE_GUANLIYUANCHAXUNHONGWAIZHEDANGQINGKUANG){//管理员查询红外遮挡情况
            $lattice = DeviceLattice::where(['device_id' => $device_id,'deletetime' => null])->select();
            $data = $message['message'];
            $device = Device::where(['id' => $device_id])->find();
            foreach($lattice as $k => $v){
                if (array_key_exists("cabinet_state_{$v['number']}",$data)){
                    $device_lattice = DeviceLattice::where(['id' => $v['id']])->find();
                    DeviceLattice::where(['id' => $v['id']])->update([
                        'infrared_type' => $data["cabinet_state_{$v['number']}"],
                        'infrared_time' => time(),
                    ]);
                    if ($device->is_infra_red == Device::IS_INFRA_RED_YOU) {//有红外
                        if($data["cabinet_state_{$v['number']}"] == 0 && $device_lattice->block_id != null){//红外遮挡:0=物品遮挡
                            $device_lattice->use_status = DeviceLattice::USE_STATUS_YOUGAN;
                        }else{
                            $device_lattice->use_status = DeviceLattice::USE_STATUS_WUGAN;
                        }
                    }
                    $device_lattice->save();
                }
            }
        }elseif ($instruction->control_type == DeviceInstruction::CONTROL_TYPE_GUIHUANLIUCHENGJIANCEHONGWAIZHEDANGQINGKUANG){//归还检测流程查询红外遮挡情况
            $order_device_id = LeaseOrderDevice::detectionResponse(LeaseOrderDevice::DETECTION_TYPE_infrared,$instruction->lease_order_device_id,$message);
            $return['lease_order_device_id'] = $order_device_id;
        }
        $instruction->control_status = DeviceInstruction::CONTROL_STATUS_YIYINGDA;
        $instruction->save();
        return $return;
    }

    /**
     * 卡ID读取应答
     */
    public static function cardID($device_id,$message){
        $return = [];
        $instruction = DeviceInstruction::where(['device_id' => $device_id,'code' =>Analysis::CODE_BUKA, 'message_id' => $message['message_id'],'deletetime' => null])->order('id desc')->find();
        if(!$instruction){
            return [];
        }
        //管理员查询全部隔扣卡id
        if ($instruction->control_type == DeviceInstruction::CONTROL_TYPE_GUANLIYUANDUQUKAID){
            $lattice = DeviceLattice::where(['device_id' => $device_id,'deletetime' => null])->order('number ast')->select();//查询设备下所有隔扣
            $data = $message['message'];
            $device = Device::where(['id' => $device_id])->find();
            foreach($lattice as $k => $v){
                //更新设备隔扣表中存储的卡id
                $device_lattice = DeviceLattice::where(['id' => $v['id']])->find();
                if (array_key_exists("card_number_{$v['number']}",$data)){
                    DeviceLattice::where(['id' => $v['id']])->update([
                        'block_id' => $data["card_number_{$v['number']}"] == 'NULL' ? null : $data["card_number_{$v['number']}"],
                        'block_time' => time(),
                    ]);
                    if ($device->is_infra_red == Device::IS_INFRA_RED_YOU){//有红外
                        if($data["card_number_{$v['number']}"] != 'NULL' && $device_lattice->infrared_type != 1){//红外遮挡:0=物品遮挡
                            $device_lattice->use_status = DeviceLattice::USE_STATUS_YOUGAN;
                        }else{
                            $device_lattice->use_status = DeviceLattice::USE_STATUS_WUGAN;
                        }
                    }elseif ($device->is_infra_red == Device::IS_INFRA_RED_WU){//无红外
                        if($data["card_number_{$v['number']}"] != 'NULL'){//红外遮挡:0=物品遮挡
                            $device_lattice->use_status = DeviceLattice::USE_STATUS_YOUGAN;
                        }else{
                            $device_lattice->use_status = DeviceLattice::USE_STATUS_WUGAN;
                        }
                    }
                    $device_lattice->save();
                }
            }
        }
        //管理员查询单个隔扣卡id
        elseif ($instruction->control_type == DeviceInstruction::CONTROL_TYPE_DULICHAXUN){
            $data = $message['message'];
            $device_lattice = DeviceLattice::where(['id' => $instruction->device_lattice_id,'deletetime' => null])->find();//查询隔扣记录
            if($device_lattice){
                $device_lattice->block_id = $data["card_number_1"] == 'NULL' ? null : $data["card_number_1"];
                $device_lattice->block_time = time();
                $device = Device::where(['id' => $device_id])->find();
                if ($device->is_infra_red == Device::IS_INFRA_RED_YOU){//有红外
                    if($data["card_number_1"] != 'NULL' && $device_lattice->infrared_type != 1){//红外遮挡:0=物品遮挡
                        $device_lattice->use_status = DeviceLattice::USE_STATUS_YOUGAN;
                    }else{
                        $device_lattice->use_status = DeviceLattice::USE_STATUS_WUGAN;
                    }
                }elseif ($device->is_infra_red == Device::IS_INFRA_RED_WU){//无红外
                    if($data["card_number_1"] != 'NULL'){//红外遮挡:0=物品遮挡
                        $device_lattice->use_status = DeviceLattice::USE_STATUS_YOUGAN;
                    }else{
                        $device_lattice->use_status = DeviceLattice::USE_STATUS_WUGAN;
                    }
                }

                $device_lattice->save();

                $new_device_lattice = DeviceLattice::where(['device_id' => $device_id,'deletetime' => null,'number' => ['>',$device_lattice->number]])->order('number asc')->find();//查询新的隔扣记录
                if ($new_device_lattice){
                    $queue_default = config('queue.default');
                    Queue::later(1, "app\common\job\Device@obtainNfcId", [
                        'device_id' => $new_device_lattice->device_id,
                        'device_lattice_id' => $new_device_lattice->id
                    ], $queue_default);
                }
            }
        }
        //用户下单读取隔扣卡id
        elseif ($instruction->control_type == DeviceInstruction::CONTROL_TYPE_YONGHUXIADANDUQUKAID){
            $order_device = LeaseOrderDevice::where(['id' => $instruction->lease_order_device_id,'deletetime' => null])->find();
            if ($message['message']['card_number_1'] == "NULL"){//未读取到设备中的id卡号
                //取消订单
                trace(["13========================处理lease_order_id报错问题_cardID==============================" => $order_device],'error');
                LeaseOrder::orderCancell($order_device->lease_order_id,LeaseOrder::CANCELL_TYPE_ZULINQIANWEIDUDAOKAID);
            }elseif ($message['message']['card_number_1'] != "NULL"){//读取到了设备中的id卡号
                //在订单中记录设备id卡号
                LeaseOrderDevice::where(['id' => $instruction->lease_order_device_id])->update([
                    'block_id' => $message['message']['card_number_1']
                ]);
                //执行开门流程
                //开始开锁
                $queue_default = config('queue.default');
                //Queue::later(1, "app\common\job\Lease@orderStartRenting", ['lease_order_id' => $order_device->lease_order_id], $queue_default);
                trace(["14========================处理lease_order_id报错问题_cardID 1==============================" => $order_device],'error');
                Queue::push("app\common\job\Lease@orderStartRenting", ['lease_order_id' => $order_device->lease_order_id], $queue_default);
            }
            $return['device_lattice_id'] =  $order_device->device_lattice_id;
            $return['lease_order_device_id'] =  $instruction->lease_order_device_id;
        }
        //归还检测流程查询杆子卡id
        elseif ($instruction->control_type == DeviceInstruction::CONTROL_TYPE_GUIHUANJIANCEKAID){
            $order_device_id = LeaseOrderDevice::detectionResponse(LeaseOrderDevice::DETECTION_TYPE_block,$instruction->lease_order_device_id,$message);
            $return['lease_order_device_id'] = $order_device_id;
        }
        $instruction->control_status = DeviceInstruction::CONTROL_STATUS_YIYINGDA;
        $instruction->save();
        return $return;
    }


}
